use minifb::{Key, Window, WindowOptions};
use rand::Rng;
use std::time::{Duration, Instant};

// 屏幕尺寸常量
const SCREEN_WIDTH: usize = 800;
const SCREEN_HEIGHT: usize = 600;

// 颜色定义（RGBA）
const COLOR_BLACK: u32 = 0x000000;
const COLOR_WHITE: u32 = 0xFFFFFF;
const COLOR_RED: u32 = 0xFF0000;
const COLOR_GREEN: u32 = 0x00FF00;

// 玩家/子弹/敌人结构体（不变）
#[derive(Debug, Clone, Copy)]
struct Player {
    x: f32,
    y: f32,
    width: f32,
    height: f32,
    speed: f32, // 像素/秒（帧率无关）
}

#[derive(Debug, Clone, Copy)] // 改为 Copy，方便插值
struct Bullet {
    x: f32,
    y: f32,
    width: f32,
    height: f32,
    speed: f32,
}

#[derive(Debug, Clone, Copy)] // 改为 Copy，方便插值
struct Enemy {
    x: f32,
    y: f32,
    width: f32,
    height: f32,
    speed: f32,
}

// 游戏状态结构体（拆分“当前状态”和“上一帧状态”，用于插值）
struct GameState {
    // 当前状态（用于更新逻辑）
    current: CurrentState,
    // 上一帧状态（用于渲染插值）
    previous: CurrentState,
    // 累计未更新的时间（固定时间步用）
    accumulated_time: Duration,
}

// 实际存储游戏数据的结构体
#[derive(Debug, Clone)]
struct CurrentState {
    player: Player,
    bullets: Vec<Bullet>,
    enemies: Vec<Enemy>,
    score: u32,
    last_enemy_spawn: Instant,
    enemy_spawn_interval: Duration,
}

impl GameState {
    fn new() -> Self {
        let initial_current = CurrentState {
            player: Player {
                x: (SCREEN_WIDTH as f32 - 50.0) / 2.0,
                y: SCREEN_HEIGHT as f32 - 100.0,
                width: 50.0,
                height: 50.0,
                speed: 300.0, // 像素/秒（帧率无关）
            },
            bullets: Vec::new(),
            enemies: Vec::new(),
            score: 0,
            last_enemy_spawn: Instant::now(),
            enemy_spawn_interval: Duration::from_secs(1),
        };
        GameState {
            current: initial_current.clone(),
            previous: initial_current,
            accumulated_time: Duration::ZERO,
        }
    }

    // 处理输入（不变，仍基于 delta_time 控制移动速度）
    fn handle_input(&mut self, window: &Window, delta_time: f32) {
        let player = &mut self.current.player;
        if window.is_key_down(Key::A) || window.is_key_down(Key::Left) {
            player.x -= player.speed * delta_time;
        }
        if window.is_key_down(Key::D) || window.is_key_down(Key::Right) {
            player.x += player.speed * delta_time;
        }
        // 限制玩家在屏幕内
        player.x = player.x.max(0.0).min(SCREEN_WIDTH as f32 - player.width);

        // 发射子弹（限制连发）
        if (window.is_key_down(Key::Space) || window.is_key_down(Key::Up))
            && self.current.bullets.len() < 5
        {
            let bullet = Bullet {
                x: player.x + player.width / 2.0 - 2.5,
                y: player.y,
                width: 5.0,
                height: 15.0,
                speed: 500.0, // 像素/秒（帧率无关）
            };
            self.current.bullets.push(bullet);
        }
    }

    // 固定时间步更新（核心修改！）
    // fixed_timestep：固定更新步长（比如 1/120 秒）
    fn fixed_update(&mut self, fixed_timestep: f32) {
        let state = &mut self.current;

        // 1. 更新子弹
        state.bullets.retain_mut(|bullet| {
            bullet.y -= bullet.speed * fixed_timestep;
            bullet.y + bullet.height > 0.0
        });

        // 2. 生成敌人
        if Instant::now() - state.last_enemy_spawn > state.enemy_spawn_interval {
            let mut rng = rand::thread_rng();
            let enemy = Enemy {
                x: rng.gen_range(0.0..=(SCREEN_WIDTH as f32 - 40.0)),
                y: -40.0,
                width: 40.0,
                height: 40.0,
                speed: 200.0, // 像素/秒（帧率无关）
            };
            state.enemies.push(enemy);
            state.last_enemy_spawn = Instant::now();
        }

        // 3. 更新敌人
        state.enemies.retain_mut(|enemy| {
            enemy.y += enemy.speed * fixed_timestep;
            enemy.y < SCREEN_HEIGHT as f32
        });

        // 4. 碰撞检测
        let mut hit_bullets = Vec::new();
        let mut hit_enemies = Vec::new();
        for (bullet_idx, bullet) in state.bullets.iter().enumerate() {
            for (enemy_idx, enemy) in state.enemies.iter().enumerate() {
                if rect_collision(
                    (bullet.x, bullet.y, bullet.width, bullet.height),
                    (enemy.x, enemy.y, enemy.width, enemy.height),
                ) {
                    hit_bullets.push(bullet_idx);
                    hit_enemies.push(enemy_idx);
                    state.score += 10;
                }
            }
        }
        // 倒序移除碰撞物体
        for &idx in hit_bullets.iter().rev() {
            state.bullets.remove(idx);
        }
        for &idx in hit_enemies.iter().rev() {
            state.enemies.remove(idx);
        }
    }

    // 渲染插值（核心修改！用 alpha 混合上一帧和当前帧状态）
    // alpha：插值系数（0~1，0=完全上一帧，1=完全当前帧）
    fn render_interpolated(&self, buffer: &mut [u32], alpha: f32) {
        buffer.fill(COLOR_BLACK);

        // 1. 插值玩家位置（x 坐标线性插值）
        let player_x = lerp(self.previous.player.x, self.current.player.x, alpha);
        let player_y = lerp(self.previous.player.y, self.current.player.y, alpha);
        draw_rect(
            buffer,
            player_x,
            player_y,
            self.current.player.width,
            self.current.player.height,
            COLOR_GREEN,
        );

        // 2. 插值子弹位置（注意：子弹是动态生成的，这里简化为取当前帧，复杂场景需处理生成/销毁插值）
        for bullet in &self.current.bullets {
            draw_rect(
                buffer,
                bullet.x,
                bullet.y,
                bullet.width,
                bullet.height,
                COLOR_WHITE,
            );
        }

        // 3. 插值敌人位置
        for (prev_enemy, curr_enemy) in self
            .previous
            .enemies
            .iter()
            .zip(self.current.enemies.iter())
        {
            let enemy_x = lerp(prev_enemy.x, curr_enemy.x, alpha);
            let enemy_y = lerp(prev_enemy.y, curr_enemy.y, alpha);
            draw_rect(
                buffer,
                enemy_x,
                enemy_y,
                curr_enemy.width,
                curr_enemy.height,
                COLOR_RED,
            );
        }
    }
}

// 线性插值函数（用于渲染插值）
fn lerp(a: f32, b: f32, alpha: f32) -> f32 {
    a + (b - a) * alpha.clamp(0.0, 1.0) // alpha 限制在 0~1，避免越界
}

// 矩形碰撞检测（不变）
fn rect_collision(rect1: (f32, f32, f32, f32), rect2: (f32, f32, f32, f32)) -> bool {
    let (x1, y1, w1, h1) = rect1;
    let (x2, y2, w2, h2) = rect2;
    x1 < x2 + w2 && x1 + w1 > x2 && y1 < y2 + h2 && y1 + h1 > y2
}

// 绘制矩形（不变）
fn draw_rect(buffer: &mut [u32], x: f32, y: f32, width: f32, height: f32, color: u32) {
    let x_start = x.floor() as usize;
    let y_start = y.floor() as usize;
    let x_end = (x + width).ceil() as usize;
    let y_end = (y + height).ceil() as usize;

    let x_start = x_start.max(0).min(SCREEN_WIDTH);
    let x_end = x_end.max(0).min(SCREEN_WIDTH);
    let y_start = y_start.max(0).min(SCREEN_HEIGHT);
    let y_end = y_end.max(0).min(SCREEN_HEIGHT);

    for y in y_start..y_end {
        for x in x_start..x_end {
            let index = y * SCREEN_WIDTH + x;
            buffer[index] = color;
        }
    }
}

fn main() {
    // 创建窗口（不变）
    let mut window = Window::new(
        "Rust 动态 FPS 打飞机 - 适配 30~160+ FPS",
        SCREEN_WIDTH,
        SCREEN_HEIGHT,
        WindowOptions::default(),
    )
    .expect("创建窗口失败");

    // 像素缓冲区（不变）
    let mut buffer = vec![COLOR_BLACK; SCREEN_WIDTH * SCREEN_HEIGHT];

    // 初始化游戏状态（不变）
    let mut game_state = GameState::new();

    // 主循环计时（修改：取消固定 FPS，改为累计时间）
    let mut last_frame_time = Instant::now();
    // 固定更新步长（1/120 秒 ≈ 8.33ms，转换为纳秒：1e9 纳秒 = 1 秒）
    const FIXED_TIMESTEP: f32 = 1.0 / 120.0;
    // 修复：用 from_nanos（const 函数）定义最大累计时间（0.25 秒 = 250_000_000 纳秒）
    const MAX_ACCUMULATED_TIME: Duration = Duration::from_nanos(250_000_000);

    // 游戏主循环（核心修改！）
    while window.is_open() && !window.is_key_down(Key::Escape) {
        // 1. 计算当前帧耗时（delta time）
        let now = Instant::now();
        let frame_duration = now - last_frame_time;
        last_frame_time = now;

        // 2. 累计时间（用于固定时间步更新）
        game_state.accumulated_time += frame_duration;
        // 限制最大累计时间（避免卡顿导致的巨帧）
        game_state.accumulated_time = game_state.accumulated_time.min(MAX_ACCUMULATED_TIME);

        // 3. 处理输入（用当前帧的 delta time，确保输入响应速度与帧率无关）
        let delta_time = frame_duration.as_secs_f32();
        game_state.handle_input(&window, delta_time);

        // 4. 固定时间步更新（关键！累计时间够一个固定步长，就更新一次）
        // 修复：用 from_nanos 构造固定步长的 Duration
        while game_state.accumulated_time >= Duration::from_nanos((FIXED_TIMESTEP * 1e9) as u64) {
            // 保存当前状态为“上一帧状态”（用于后续插值）
            game_state.previous = game_state.current.clone();
            // 执行固定步长更新
            game_state.fixed_update(FIXED_TIMESTEP);
            // 减去一个固定步长的时间
            game_state.accumulated_time -= Duration::from_nanos((FIXED_TIMESTEP * 1e9) as u64);
        }

        // 5. 计算插值系数 alpha（累计时间 / 固定步长，0~1）
        let alpha = game_state.accumulated_time.as_secs_f32() / FIXED_TIMESTEP;

        // 6. 插值渲染（用 alpha 混合上一帧和当前帧，画面流畅）
        game_state.render_interpolated(&mut buffer, alpha);

        // 7. 更新窗口（不变）
        window
            .update_with_buffer(&buffer, SCREEN_WIDTH, SCREEN_HEIGHT)
            .expect("更新窗口失败");

        // 取消固定 FPS 的 sleep，让渲染跑满硬件最大能力！
    }
}
